package com.pudu.mydemo.utils;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Handler;
import android.util.Log;
import android.widget.ImageView;
import org.apache.commons.io.IOUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class FasterAnimationDrawable {

    private static boolean mShouldRun;
    private static boolean mOneShot;
    private static FasterAnimationDrawable mInstance;
    private Bitmap recycleBitmap;
    private Handler handler;
    public static class MyFrame {
        byte[] bytes;
        int duration;
        int id;
        Drawable drawable;
        boolean isReady = false;
    }

    public interface OnDrawableLoadedListener {
        public void onDrawableLoaded(List<MyFrame> myFrames);
    }

    public FasterAnimationDrawable() {
        init();
    }

    public void init() {
        handler = new Handler();
    }

    public static FasterAnimationDrawable getInstance() {
        if(mInstance == null) {
            mInstance = new FasterAnimationDrawable();
        }
        mInstance.recycleBitmap = null;
//        handler = new Handler();
        return mInstance;
    }
    public  void animateRawManuallyFromXML(int resourceId,
                                                 final ImageView imageView, final Runnable onStart,
                                                 final Runnable onComplete) {
        loadRaw(resourceId, imageView.getContext(),
                new OnDrawableLoadedListener() {
                    @Override
                    public void onDrawableLoaded(List<MyFrame> myFrames) {
                        if (onStart != null) {
                            onStart.run();
                        }
                        animateRawManually(myFrames, imageView, onComplete);
                    }
                });
    }

    public  void setOneShot(boolean oneShot) {
        mOneShot = oneShot;
    }


    public void pause() {
        handler.removeCallbacksAndMessages(null);
        Log.e("guiliu","remove call back message");
    }
    public  void setShouldRun(boolean shouldRun) {
        mShouldRun = shouldRun;
    }
    /**
     * Stops the animation
     */
    public  synchronized void stop() {
        mShouldRun = false;
    }

    //
    private  void loadRaw(final int resourceId, final Context context,
                                final OnDrawableLoadedListener onDrawableLoadedListener) {
        loadFromXml(resourceId, context, onDrawableLoadedListener);
    }

    //
    private  void loadFromXml(final int resourceId,
                                    final Context context,
                                    final OnDrawableLoadedListener onDrawableLoadedListener) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                final ArrayList<MyFrame> myFrames = new ArrayList<MyFrame>();
                Log.e("guiliu","init myframes size:" +myFrames.size());
                XmlResourceParser parser = context.getResources().getXml(
                        resourceId);

                try {
                    int eventType = parser.getEventType();
                    while (eventType != XmlPullParser.END_DOCUMENT) {
                        if (eventType == XmlPullParser.START_DOCUMENT) {

                        } else if (eventType == XmlPullParser.START_TAG) {

                            if (parser.getName().equals("item")) {
                                byte[] bytes = null;
                                int duration = 1000;
                                int resId = 0;
                                for (int i = 0; i < parser.getAttributeCount(); i++) {
                                    if (parser.getAttributeName(i).equals(
                                            "drawable")) {
                                         resId = Integer.parseInt(parser
                                                .getAttributeValue(i)
                                                .substring(1));
                                        bytes = IOUtils.toByteArray(context
                                                .getResources()
                                                .openRawResource(resId));
                                    } else if (parser.getAttributeName(i)
                                            .equals("duration")) {
                                        duration = parser.getAttributeIntValue(
                                                i, 1000);
                                    }
                                }

                                MyFrame myFrame = new MyFrame();
                                myFrame.bytes = bytes;
                                myFrame.duration = duration;
                                myFrame.id = resId;
                                myFrames.add(myFrame);
                            }

                        } else if (eventType == XmlPullParser.END_TAG) {

                        } else if (eventType == XmlPullParser.TEXT) {

                        }

                        eventType = parser.next();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (XmlPullParserException e2) {
                    // TODO: handle exception
                    e2.printStackTrace();
                }

                // Run on UI Thread
                new Handler(context.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        if (onDrawableLoadedListener != null) {
                            onDrawableLoadedListener.onDrawableLoaded(myFrames);
                        }
                    }
                });
            }
        }).run();
    }


    //
    private  void animateRawManually(List<MyFrame> myFrames,
                                           ImageView imageView, Runnable onComplete) {
        animateRawManually(myFrames, imageView, onComplete, 0);
    }
    BitmapFactory.Options options = new BitmapFactory.Options();

    private class GetImageDrawableTask extends AsyncTask<MyFrame, Void, Bitmap> {

        private ImageView mImageView;

        public GetImageDrawableTask(ImageView imageView) {
            mImageView = imageView;
        }

        @SuppressLint("NewApi")
        @Override
        protected Bitmap doInBackground(MyFrame... params) {
//            byte[] bytes = null;
            options.inMutable = true;
            if (recycleBitmap != null)
                options.inBitmap = recycleBitmap;
//            Log.e("fastanimation","id: "+params[0].id);
//            recycleBitmap = BitmapFactory.decodeResource(mImageView.getContext().getResources(), params[0].id, options);
          /*  try {
               char [] a = new char[10];
                a[1] = 1;a[2] =2;
                //解析成字节不会导致丢帧
                bytes = IOUtils.toByteArray(
                        mImageView.getContext().getResources().openRawResource(params[0].id));
                recycleBitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length,options);
            } catch (IOException e) {
                e.printStackTrace();
            }*/
            recycleBitmap = BitmapFactory.decodeByteArray(params[0].bytes, 0, params[0].bytes.length,options);
            return recycleBitmap;
        }

        @Override
        protected void onPostExecute(Bitmap result) {
            super.onPostExecute(result);
            if(result!=null)
               mImageView.setImageBitmap(result);

         /*   if (mRecycleableBitmapDrawable == null) {
                mRecycleableBitmapDrawable = new ImageViewBitmapDrawable(
                        mContext.getResources(), bm);
            } else {
                mRecycleableBitmapDrawable.setBitmap(bm);
            }
            setImageDrawable(mRecycleableBitmapDrawable);*/
//            if (mOnAnimationFrameChangedListener != null)
//                mOnAnimationFrameChangedListener.onAnimationFrameChanged(mIndex);
        }

    }
    //一直在循环的是这个
    private  void animateRawManually(final List<MyFrame> myFrames,
                                           final ImageView imageView, final Runnable onComplete,
                                           final int frameNumber) {
        final MyFrame thisFrame = myFrames.get(frameNumber);

        GetImageDrawableTask getImageDrawableTask = new GetImageDrawableTask(imageView);
        getImageDrawableTask.execute(thisFrame);
//        Glide.with(imageView.getContext())
//                .load(thisFrame.id)
//                .into(imageView);
//        Picasso.with(imageView.getContext()).load(thisFrame.id).into(imageView);
//        Log.e("guiliu","size: "+myFrames.size());
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if(!mShouldRun) return;
                // Make sure ImageView hasn't been changed to a different Image
                // in this time

                    if (frameNumber + 1 < myFrames.size()) {
//                        MyFrame nextFrame = myFrames.get(frameNumber + 1);
                        animateRawManually(myFrames, imageView, onComplete,
                                frameNumber + 1);
                       /* if (nextFrame.isReady) {
                            // Animate next frame
                            animateRawManually(myFrames, imageView, onComplete,
                                    frameNumber + 1);
                        } else {
                            nextFrame.isReady = true;
                        }*/
                    } else {

                        Log.e("guiliu","oneshot:"+mOneShot);
                        if(mOneShot) {
                            animateRawManually(myFrames, imageView, onComplete,
                                    0);
                        }

                        if (onComplete != null) {
                            onComplete.run();
                        }
                    }

            }
        }, thisFrame.duration);

    }


}
